package cqrtplm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hustcad.plm.basic.log.LogEventEnum;
import com.hustcad.plm.basic.log.TyplmLogger;
import com.hustcad.plm.basic.util.TyplmEntityBaseUtil;
import com.hustcad.plm.pdm.common.util.CommonUtil;
import com.hustcad.plm.pdm.file.model.constant.FileErrorCodeEnum;
import com.hustcad.plm.pdm.file.service.TyplmFileHandleService;
import com.hustcad.plm.pdm.file.service.TyplmFileService;
import com.hustcad.plm.pdm.filevault.model.vo.FileDataVO;
import com.hustcad.plm.pdm.workflow.model.dto.AdvancedFlowContainerCondition;
import com.hustcad.plm.pdm.workflow.model.entity.WorkFlowContainerView;
import com.hustcad.plm.pdm.workflow.model.vo.AdvancedFlowContainerVO;
import com.hustcad.plm.pdm.workflow.service.TyplmWorkFlowContainerService;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.entity.CTyEntityBaseDO;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.audit.AuditLogDO;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.response.ResponseResult;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.session.TyAccountContext;
import com.ty.basic.utils.ArgumentUtils;
import com.ty.security.util.TyCommonUtils;
import cqrtplm.constant.RTPlmConstant;
import cqrtplm.dto.DocLinkNameDTO;
import cqrtplm.dto.KnowledgePushDTO;
import cqrtplm.dto.RTAttributeCardDTO;
import cqrtplm.dto.RtCustomerNodeInfoDTO;
import cqrtplm.entity.RtCustomerNodeInfoDO;
import cqrtplm.entity.RtCustomerNodeInfoLinkDO;
import cqrtplm.mapper.RTKnowledgePushMapper;
import cqrtplm.service.RTKnowledgePushService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.hustcad.plm.pdm.flowbusiness.model.entity.WorkFlowObjectPackage;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.util.Map;

@Service
@Transactional
public class RTKnowledgePushServiceImpl implements RTKnowledgePushService {


    @Resource
    private RTKnowledgePushMapper rtKnowledgePushMapper;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;
    @Resource
    private TyplmFileHandleService fileHandleService;
    @Resource
    private TyplmLogger typlmLogger;
    @Resource
    private TyplmFileService typlmFileService;
    @Resource
    private TyplmWorkFlowContainerService typlmWorkFlowContainerService;


    @Override
    public ResponseResult<RtCustomerNodeInfoDO> addKnowledgeInfo(RtCustomerNodeInfoDTO customerNodeInfoDTO) {
        String customerStr = customerNodeInfoDTO.getCustomer().stream()
                .map(String::trim)
                .collect(Collectors.joining(","));
        String nodeName = customerNodeInfoDTO.getNodeName().stream()
                .map(String::trim)
                .collect(Collectors.joining(","));
        RtCustomerNodeInfoDO CustomerNodeInfo = new RtCustomerNodeInfoDO(null,customerNodeInfoDTO.getOtype(),
                                                                         customerStr,nodeName,customerNodeInfoDTO.getPushContent());
        buildCommonFiled(CustomerNodeInfo);
        //新增文档
        if (CollectionUtils.isNotEmpty(customerNodeInfoDTO.getDocLinkName())) {
            buildCustomerNode(customerNodeInfoDTO, CustomerNodeInfo);
        }
        //新增文本
        rtKnowledgePushMapper.insertKnowledgeInfo(CustomerNodeInfo);
        return ResponseResult.success(CustomerNodeInfo);
    }

    private void buildCommonFiled(RtCustomerNodeInfoDO CustomerNodeInfo) {
        CustomerNodeInfo.setOid(snowflakeIdComponent.getInstance().nextId());
        TyplmEntityBaseUtil.fillCommonFieldForCreate(CustomerNodeInfo);
        UserDO user = TyAccountContext.getUser();
        CustomerNodeInfo.setNewPersonAdded(user.getName());
        CustomerNodeInfo.setModifiedBy(user.getName());
        CustomerNodeInfo.setTerminatingPerson(user.getName());
    }

    private void buildCustomerNode(RtCustomerNodeInfoDTO customerNodeInfoDTO, RtCustomerNodeInfoDO customerNodeInfo) {
        List<RtCustomerNodeInfoLinkDO> customerNodeInfolist = new ArrayList<>();
        customerNodeInfo.setPushContent(RTPlmConstant.ZERO);
        if (CollUtil.isNotEmpty(customerNodeInfoDTO.getDocLinkName())) {
            for (DocLinkNameDTO dto : customerNodeInfoDTO.getDocLinkName()) {
                RtCustomerNodeInfoLinkDO customerNodeInfoLinkDO = new RtCustomerNodeInfoLinkDO();
                customerNodeInfoLinkDO.setOid(snowflakeIdComponent.getInstance().nextId());
                TyplmEntityBaseUtil.fillCommonFieldForCreate(customerNodeInfoLinkDO);
                customerNodeInfoLinkDO.setDocId(dto.getDocOId());
                customerNodeInfoLinkDO.setCustomerId(customerNodeInfo.getOid());
                customerNodeInfoLinkDO.setIdentifierDisplayName(dto.getIdentifierDisplayName());
                customerNodeInfoLinkDO.setDocOType(dto.getDocOType());
                customerNodeInfolist.add(customerNodeInfoLinkDO);
            }
            rtKnowledgePushMapper.batchInsert(customerNodeInfolist);
        }
    }

    @Override
    public void updateKnowledgeInfo(RtCustomerNodeInfoDTO customerNodeInfoDTO) {
        String content = rtKnowledgePushMapper.selectContentById(customerNodeInfoDTO.getOid());
        String customerStr = customerNodeInfoDTO.getCustomer().stream()
                .map(String::trim)
                .collect(Collectors.joining(","));
        String nodeName = customerNodeInfoDTO.getNodeName().stream()
                .map(String::trim)
                .collect(Collectors.joining(","));
        RtCustomerNodeInfoDO CustomerNodeInfo = new RtCustomerNodeInfoDO(null,customerNodeInfoDTO.getOtype(),
                                                                         customerStr,nodeName,customerNodeInfoDTO.getPushContent());

        if (StringUtils.equals(content, RTPlmConstant.ZERO)) {
            rtKnowledgePushMapper.deleteCustomerById(Collections.singletonList(
                    String.valueOf(customerNodeInfoDTO.getOid())));
            rtKnowledgePushMapper.batchDeleteWithLink(Collections.singletonList(
                    String.valueOf(customerNodeInfoDTO.getOid())));


            buildCommonFiled(CustomerNodeInfo);
            //新增文档
            buildCustomerNode(customerNodeInfoDTO, CustomerNodeInfo);
            //新建文本
            rtKnowledgePushMapper.insertKnowledgeInfo(CustomerNodeInfo);
        } else {
            TyplmEntityBaseUtil.fillCommonFieldForUpdate(CustomerNodeInfo);
            UserDO user = TyAccountContext.getUser();
            customerNodeInfoDTO.setNewPersonAdded(user.getName());
            customerNodeInfoDTO.setModifiedBy(user.getName());
            customerNodeInfoDTO.setTerminatingPerson(user.getName());
            rtKnowledgePushMapper.updateKnowledgeInfo(CustomerNodeInfo);
        }
    }

    @Override
    public void batchDeleteKnowledgeInfo(List<String> oids) {
        rtKnowledgePushMapper.deleteCustomerById(oids);
        rtKnowledgePushMapper.batchDeleteWithLink(oids);
    }

    @Override
    public PageInfo<RtCustomerNodeInfoDTO> searchTextByCustomer(String customer, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<RtCustomerNodeInfoDO> customers = rtKnowledgePushMapper.queryByCustomerText(customer);
        List<RtCustomerNodeInfoDTO> result = customers.stream()
                .map(customerNodeInfo -> {
                    RtCustomerNodeInfoDTO customerNodeInfoDTO = new RtCustomerNodeInfoDTO();
                    try {
                        // 先复制属性
                        // 使用 Hutool 的 BeanUtil，可以通过 excludeProperties 参数排除不需要复制的字段
                        BeanUtil.copyProperties(customerNodeInfo, customerNodeInfoDTO, "customer", "nodeName");
                        // 再设置分割后的集合字段
                        customerNodeInfoDTO.setCustomer(Arrays.asList(customerNodeInfo.getCustomer().split(",")));
                        customerNodeInfoDTO.setNodeName(Arrays.asList(customerNodeInfo.getNodeName().split(",")));
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    return customerNodeInfoDTO;
                }).collect(Collectors.toList());
        return new PageInfo<>(result);
    }


    @Override
    public PageInfo<RtCustomerNodeInfoDTO> searchFileByCustomer(String customer, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<RtCustomerNodeInfoDO> customers = rtKnowledgePushMapper.queryByCustomer(customer);
        List<RtCustomerNodeInfoDTO> result = customers.stream()
                .map(customerNodeInfo -> {
                    RtCustomerNodeInfoDTO customerNodeInfoDTO = new RtCustomerNodeInfoDTO();
                    try {
                        // 先复制属性
                        BeanUtil.copyProperties(customerNodeInfo, customerNodeInfoDTO, "customer", "nodeName");
                        // 再设置分割后的集合字段
                        customerNodeInfoDTO.setCustomer(Arrays.asList(customerNodeInfo.getCustomer().split(",")));
                        customerNodeInfoDTO.setNodeName(Arrays.asList(customerNodeInfo.getNodeName().split(",")));
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    return customerNodeInfoDTO;
                }).collect(Collectors.toList());
        return new PageInfo<>(result);
    }

    @Override
    public ResponseResult searchStatusText(String oid,String currentFlowName) {
        if (oid == null) {
            return ResponseResult.fail("400", "参数toid不能为空");
        }

        TyAccountContext.setBizCommonHolderMapValue("ignoreUserDisabled", "Y");
        try {
            //获取流程对象包
            WorkFlowObjectPackage workflowobjectPackage = getWorkFlowObjectPackage(new BigInteger(oid));
            if (workflowobjectPackage == null) {
                return ResponseResult.success(null);
            }
            //通过需求状态表拿到客户编码
            String customerCode = extractCodeFromFlowObject(workflowobjectPackage);

            KnowledgePushDTO knowledgePushDTO = new KnowledgePushDTO(customerCode, currentFlowName);
            List<RtCustomerNodeInfoDTO> customers = rtKnowledgePushMapper.searchStatusText(knowledgePushDTO);

            return ResponseResult.success(customers);
        } finally {
            TyAccountContext.removeBizCommonHolderMapValue("ignoreUserDisabled");
        }
    }

    /**
     * 打包下载文件
     *
     * @param
     * @return ZIP文件的字节数据
     */
    public ResponseResult<byte[]> downloadFilesAsZip(String oid,String currentFlowName) {
        if (oid == null) {
            return ResponseResult.fail("400", "流程oid不能为空");
        }
        TyAccountContext.setBizCommonHolderMapValue("ignoreUserDisabled", "Y");

        try {
            //获取流程对象包
            WorkFlowObjectPackage workflowobjectPackage = getWorkFlowObjectPackage(new BigInteger(oid));
            if (workflowobjectPackage == null) {
                return ResponseResult.success(null);
            }
            //通过需求状态表拿到客户编码
            String customerCode = extractCodeFromFlowObject(workflowobjectPackage);
            //查找知识推送的表格
            KnowledgePushDTO knowledgePushDTO = new KnowledgePushDTO(customerCode, currentFlowName);
            List<BigInteger> bigIntegers = rtKnowledgePushMapper.searchStatusFile(knowledgePushDTO);
            if(bigIntegers.isEmpty()){
                return ResponseResult.success(null);
            }
            List<BigInteger> fileIdList = new ArrayList<>();

            for (BigInteger bigInteger : bigIntegers) {
                IdentifierEntity entity = new IdentifierEntity();
                entity.setOid(bigInteger);
                entity.setOtype(TableTypeConstrant.TY_DOC_OTYPE);

                TyCommonUtils.requireNonNull(entity, "entity");
                CommonUtil.checkIdentifierNotNull(entity);

                List<FileDataVO> fileListByEntity = this.fileHandleService.getFileListByEntity(entity);
                if (fileListByEntity != null) {
                    for (FileDataVO fileDataVO : fileListByEntity) {
                        fileIdList.add(new BigInteger(fileDataVO.getFileID()));
                    }
                }
            }

            ArgumentUtils.checkArgumentEmpty(fileIdList, FileErrorCodeEnum.FILE_ID.getLocaleMessage());

            // 日志记录前置，确保即使下载失败也能记录
            fileIdList.forEach(toid -> {
                this.typlmLogger.info(new CTyEntityBaseDO(toid, "ty.inteplm.fileVault.CTyContentData"),
                                      LogEventEnum.DOWNLOAD);
            });

            Map<String, byte[]> fileMap;
            try {
                fileMap = this.fileHandleService.downloadFile(fileIdList);
            } catch (Exception e) {
                throw new RuntimeException("文件下载失败", e);
            }

            // 创建ZIP文件
            byte[] zipData = createZipFile(fileMap);

            return ResponseResult.success(zipData);
        } finally {
            TyAccountContext.removeBizCommonHolderMapValue("ignoreUserDisabled");
        }
    }



    private WorkFlowObjectPackage getWorkFlowObjectPackage(BigInteger toid) {
        WorkFlowContainerView workFlowContainerView = this.typlmWorkFlowContainerService.getWorkFlowContainerDetailByPrimaryKey(toid);
        if (workFlowContainerView == null) {
            return null;
        }

        try {
            return (WorkFlowObjectPackage) workFlowContainerView;
        } catch (ClassCastException e) {
            throw new RuntimeException("对象转换失败", e);
        }
    }

    private String extractCodeFromFlowObject(WorkFlowObjectPackage workflowobjectPackage) {
        String code = "";
        if (workflowobjectPackage.getFlowObjectList() != null &&
                !workflowobjectPackage.getFlowObjectList().isEmpty() &&
                workflowobjectPackage.getFlowObjectList().get(0).getOid() != null) {
            code = rtKnowledgePushMapper.selectCustomecodeByOid(
                    workflowobjectPackage.getFlowObjectList().get(0).getRefObjectOid());
//            if (customecode != null) {
//                int start = customecode.indexOf('[');
//                int end = customecode.indexOf(']');
//                if (start != -1 && end != -1 && end > start) {
//                    code = customecode.substring(start + 1, end);
//                }
//            }
        }
        return code;
    }


    // 创建ZIP文件的方法
    private byte[] createZipFile(Map<String, byte[]> fileMap) {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ZipOutputStream zos = new ZipOutputStream(baos)) {

            for (Map.Entry<String, byte[]> entry : fileMap.entrySet()) {
                ZipEntry zipEntry = new ZipEntry(entry.getKey());
                zos.putNextEntry(zipEntry);
                zos.write(entry.getValue());
                zos.closeEntry();
            }

            zos.finish();
            return baos.toByteArray();
        } catch (Exception e) {

            throw new RuntimeException("创建ZIP文件失败", e);
        }
    }



}
